home *** CD-ROM | disk | FTP | other *** search
/ QRZ! Ham Radio 8 / QRZ Ham Radio Callsign Database - Volume 8.iso / pc / files / t_unix / j109lxa4.tar / unix.c < prev    next >
C/C++ Source or Header  |  1994-06-04  |  14KB  |  740 lines

  1. /*
  2.  * Timers and process delays work differently under POSIX.  The entire system
  3.  * is driven on a single select() call, which uses the timeout to detect alarms
  4.  * and the file descriptors to detect input.  An itimer is used to allow
  5.  * keyboard input to continue during lengthy activities --- which I tried to
  6.  * avoid for portability reasons, but it behaves *real* ugly otherwise.
  7.  * Especially when LakeSW.ampr.org lets 350K of SMTP mail pile up...
  8.  */
  9.  
  10. #include <stdio.h>
  11. #include <ctype.h>
  12. #include <sys/types.h>
  13. #include <sys/stat.h>
  14. #include <signal.h>
  15. #include "hardware.h"
  16. #ifdef M_UNIX
  17. #include <time.h>
  18. #include <sys/select.h>
  19. #else
  20. #include <sys/time.h>
  21. #endif
  22. #include "timer.h"
  23. #include "proc.h"
  24. #include "unixtm.h"
  25. #include "socket.h"
  26.  
  27. #ifdef NO_GETTOD
  28. #include <sys/timeb.h>
  29. #endif
  30.  
  31. #ifdef M_UNIX
  32. #ifndef bzero
  33. /* stupid bug in SCO 3.2.2 (is there any other kind for them?) */
  34. #define bzero(s,n) memset((s),0,(n))
  35. #endif
  36. #endif
  37.  
  38. /* avoid collision with libc */
  39. #define psignal j_psignal
  40.  
  41. /* and undo a collision avoidance, since we need the real one */
  42. #undef malloc
  43. #undef free
  44. extern void *malloc __ARGS((size_t));
  45. extern void free __ARGS((void *));
  46.  
  47. /* Don't use this yet... something's still calling malloc() directly */
  48. #undef LMCHECK            /* TEST memory allocation checker */
  49.  
  50. struct io
  51. {
  52.     struct io *next;
  53.     int fd;
  54.     void *event;
  55. };
  56.  
  57. char Hashtab[256];
  58. int Tick;
  59. int Keyboard;
  60. int32 Clock;
  61.  
  62. static int __istate = 1;
  63. static struct timeval Starttime;
  64. static struct io *Events;
  65. static int Shell;
  66.  
  67. /*****************************************************************************\
  68. *          Miscellanous functions not found in Unix              *
  69. \*****************************************************************************/
  70.  
  71. unsigned long
  72. filelength(fd)
  73.     int fd;
  74. {
  75.     static struct stat sb;
  76.  
  77.     if (fstat(fd, &sb) == -1)
  78.     return 0;
  79.     return sb.st_size;
  80. }
  81.  
  82. #ifdef NEED_STRCASECMP
  83.  
  84. int
  85. strcasecmp(s1, s2)
  86.     register char *s1, *s2;
  87. {
  88.     while (*s1 && *s2 && tolower(*s1) == tolower(*s2))
  89.     s1++, s2++;
  90.     return tolower(*s1) - tolower(*s2);
  91. }
  92.  
  93. #endif
  94.  
  95. #ifdef NEED_STRNCASECMP
  96.  
  97. int
  98. strncasecmp(s1, s2, n)
  99.     register char *s1, *s2;
  100.     int n;
  101. {
  102.     while (n && *s1 && *s2 && tolower(*s1) == tolower(*s2))
  103.     s1++, s2++, n--;
  104.     return n? tolower(*s1) - tolower(*s2): 0;
  105. }
  106.  
  107. #endif
  108.  
  109. char *
  110. strupr(s)
  111.     char *s;
  112. {
  113.     register char *p = s;
  114.  
  115.     while (*p)
  116.     *p = toupper(*p), p++;
  117.     return s;
  118. }
  119.  
  120. char *
  121. strlwr(s)
  122.     char *s;
  123. {
  124.     register char *p = s;
  125.  
  126.     while (*p)
  127.     *p = tolower(*p), p++;
  128.     return s;
  129. }
  130.  
  131. char *
  132. stpcpy(d, s)
  133.     register char *d;
  134.     register const char *s;
  135. {
  136.     while (*s)
  137.     *d++ = *s++;
  138.     *d = '\0';
  139.     return d;
  140. }
  141.  
  142. char *
  143. itoa(n, buf, base)
  144.     int n, base;
  145.     char *buf;
  146. {
  147.     if (base != 10)
  148.     tprintf("WARNING: itoa() passed radix %d\n", base);
  149.     sprintf(buf, "%d", n);
  150.     return buf;
  151. }
  152.  
  153. /* This was in assembler, I assume for speed. */
  154.  
  155. int16
  156. hash_ip(ipaddr)
  157.     long ipaddr;
  158. {
  159.     int h;
  160.  
  161.     h = ((ipaddr >> 16) & 0xFFFF) ^ (ipaddr & 0xFFFF);
  162.     return Hashtab[((h >> 8) & 0xFF) ^ (h & 0xFF)];
  163. }
  164.  
  165. /*****************************************************************************\
  166. *                Memory interface                  *
  167. \*****************************************************************************/
  168.  
  169. #ifdef LMCHECK
  170.  
  171. /*
  172.  * We track memory allocation via hash buckets.  This is a fixed-size hash
  173.  * table with variable-sized buckets:  we hash an address by taking some bits
  174.  * from it, and store the result in a slot in the bucket.
  175.  */
  176.  
  177. #define NMWHASH        4096    /* number of hash buckets - s/b power of 2 */
  178. #define LOGNMWH        12    /* log2(NMWHASH) */
  179. #define NMWHSHIFT    8    /* ptr shift for hashing */
  180. #define NMWHSLOT    32    /* initial slots in bucket */
  181.  
  182. struct hbucket
  183. {
  184.     void **ptr;
  185.     int nptr;
  186. };
  187.  
  188. static struct hbucket MWhashtab[NMWHASH];
  189.  
  190. static void
  191. mwhash(void *p)
  192. {
  193.     register struct hbucket *h;
  194.     int i;
  195.  
  196.     h = MWhashtab + (((unsigned long) p >> NMWHSHIFT) & (NMWHASH - 1));
  197.     if (!h->nptr)
  198.     {
  199.     h->ptr = malloc(NMWHSLOT * sizeof *h->ptr);
  200.     memset(h->ptr, 0, NMWHSLOT * sizeof *h->ptr);
  201.     i = 0;
  202.     }
  203.     else
  204.     {
  205.     for (i = 0; i < h->nptr; i++)
  206.     {
  207.         if (!h->ptr[i])
  208.         break;
  209.     }
  210.     if (i == h->nptr)
  211.     {
  212.         h->ptr = realloc(h->ptr, (h->nptr + NMWHSLOT) * sizeof *h->ptr);
  213.         memset(h->ptr + h->nptr, 0, NMWHSLOT * sizeof *h->ptr);
  214.         h->nptr += NMWHSLOT;
  215.     }
  216.     }
  217.     h->ptr[i] = p;
  218. }
  219.  
  220. static int
  221. mwunhash(void *p)
  222. {
  223.     register struct hbucket *h;
  224.     int i;
  225.  
  226.     h = MWhashtab + (((unsigned long) p >> NMWHSHIFT) & (NMWHASH - 1));
  227.     for (i = h->nptr; i--; )
  228.     {
  229.     if (h->ptr[i] == p)
  230.         break;
  231.     }
  232.     if (i == -1)
  233.     return 0;
  234.     h->ptr[i] = 0;
  235.     return 1;
  236. }
  237.  
  238. #endif
  239.  
  240. void *
  241. mallocw(unsigned size)
  242. {
  243.     void *p;
  244.  
  245.     if (!(p = malloc(size)))
  246.     where_outta_here(1);
  247. #ifdef LMCHECK
  248.     mwhash(p);
  249. #endif
  250.     return p;
  251. }
  252.  
  253. void *
  254. callocw(cnt, size)
  255.     unsigned cnt, size;
  256. {
  257.     void *p;
  258.  
  259.     if (!(p = malloc(size * cnt)))
  260.     where_outta_here(1);
  261. #ifdef LMCHECK
  262.     mwhash(p);
  263. #endif
  264.     memset(p, 0, size * cnt);
  265.     return p;
  266. }
  267.  
  268. void
  269. j_free(void *p)
  270. {
  271. #ifdef LMCHECK
  272.     if (!mwunhash(p))
  273.     {
  274.     printf("\r\7WARNING: free()ing unknown pointer %lx\r\n",
  275.            (unsigned long) p);
  276.     return;
  277.     }
  278. #endif
  279.     free(p);
  280. }
  281.  
  282. #if 0
  283.  
  284. /*
  285.  * these should by rights try to determine the available VM... oh, well
  286.  */
  287.  
  288. unsigned long
  289. availmem()
  290. {
  291. #ifdef linux
  292.     return 0xC0000000 - (unsigned long) sbrk(0);
  293. #else
  294.     return 0x80000000 - (unsigned long) sbrk(0);
  295. #endif
  296. }
  297.  
  298. unsigned long
  299. farcoreleft()
  300. {
  301. #ifdef linux
  302.     return 0xC0000000 - (unsigned long) sbrk(0);
  303. #else
  304.     return 0x80000000 - (unsigned long) sbrk(0);
  305. #endif
  306. }
  307.  
  308. unsigned long
  309. getss()
  310. {
  311.     return 0;
  312. }
  313.  
  314. #endif
  315.  
  316. /*****************************************************************************\
  317. *            Interrupt management - null                  *
  318. \*****************************************************************************/
  319.  
  320. int
  321. istate()
  322. {
  323.     return __istate;
  324. }
  325.  
  326. int
  327. dirps()
  328. {
  329.     sigset_t s;
  330.     int ops;
  331.  
  332.     if (__istate)
  333.     {
  334.     sigemptyset(&s);
  335.     sigaddset(&s, SIGALRM);
  336.     sigprocmask(SIG_BLOCK, &s, (sigset_t *) 0);
  337.     }
  338.     ops = __istate;
  339.     __istate = 0;
  340.     return ops;
  341. }
  342.  
  343. void
  344. restore(ps)
  345.     int ps;
  346. {
  347.     sigset_t s;
  348.  
  349.     if (__istate != ps)
  350.     {
  351.     sigemptyset(&s);
  352.     sigaddset(&s, SIGALRM);
  353.     sigprocmask((ps? SIG_UNBLOCK: SIG_BLOCK), &s, (sigset_t *) 0);
  354.     }
  355.     __istate = ps;
  356. }
  357.  
  358. /*****************************************************************************\
  359. *                  Date and time functions                  *
  360. \*****************************************************************************/
  361.  
  362. long
  363. secclock()
  364. {
  365. #ifdef NO_GETTOD
  366.     static struct timeb t;
  367.  
  368.     ftime(&t);
  369.     return t.time - Starttime.tv_sec - (Starttime.tv_usec > t.millitm * 1000);
  370. #else
  371.     static struct timezone tz;
  372.     static struct timeval tv;
  373.  
  374.     gettimeofday(&tv, &tz);
  375.     return tv.tv_sec - Starttime.tv_sec - (Starttime.tv_usec > tv.tv_usec);
  376. #endif
  377. }
  378.  
  379. long
  380. msclock()
  381. {
  382. #ifdef NO_GETTOD
  383.     static struct timeb t;
  384.  
  385.     ftime(&t);
  386.     t.millitm *= 1000;
  387.     if (t.millitm < Starttime.tv_usec)
  388.     {
  389.     t.millitm += 1000000;
  390.     t.time--;
  391.     }
  392.     return (t.time - Starttime.tv_sec) * 1000 +
  393.     (t.millitm - Starttime.tv_usec) / 1000;
  394. #else
  395.     static struct timezone tz;
  396.     static struct timeval tv;
  397.  
  398.     gettimeofday(&tv, &tz);
  399.     if (tv.tv_usec < Starttime.tv_usec)
  400.     {
  401.     tv.tv_usec += 1000000;
  402.     tv.tv_sec--;
  403.     }
  404.     return (tv.tv_sec - Starttime.tv_sec) * 1000 +
  405.     (tv.tv_usec - Starttime.tv_usec) / 1000;
  406. #endif
  407. }
  408.  
  409. static void
  410. init_time(void)
  411. {
  412. #ifdef NO_GETTOD
  413.     struct timeb t;
  414.  
  415.     ftime(&t);
  416.     Starttime.tv_sec = t.time;
  417.     Starttime.tv_usec = t.millitm * 1000;
  418. #else
  419.     struct timezone tz;
  420.  
  421.     gettimeofday(&Starttime, &tz);
  422. #endif
  423. }
  424.  
  425. void
  426. gettime(tp)
  427.     struct time *tp;
  428. {
  429.     struct tm *tm;
  430. #ifdef NO_GETTOD
  431.     static struct timeb tb;
  432.  
  433.     ftime(&tb);
  434.     tm = localtime(&tb.time);
  435.     tp->ti_hund = tb.millitm / 10;
  436. #else
  437.     static struct timeval tv;
  438.     static struct timezone tz;
  439.  
  440.     gettimeofday(&tv, &tz);
  441.     tm = localtime(&tv.tv_sec);
  442.     tp->ti_hund = tv.tv_usec / 10000;
  443. #endif
  444.     tp->ti_hour = tm->tm_hour;
  445.     tp->ti_min = tm->tm_min;
  446.     tp->ti_sec = tm->tm_sec;
  447. }
  448.  
  449. void
  450. getdate(dp)
  451.     struct date *dp;
  452. {
  453.     struct tm *tm;
  454. #ifdef NO_GETTOD
  455.     static struct timeb tb;
  456.  
  457.     ftime(&tb);
  458.     tm = localtime(&tb.time);
  459. #else
  460.     static struct timeval tv;
  461.     static struct timezone tz;
  462.  
  463.     gettimeofday(&tv, &tz);
  464.     tm = localtime(&tv.tv_sec);
  465. #endif
  466.     dp->da_year = tm->tm_year + 1900;
  467.     dp->da_mon = tm->tm_mon + 1;
  468.     dp->da_day = tm->tm_mday;
  469. }
  470.  
  471. long
  472. dostounix(dp, tp)
  473.     struct date *dp;
  474.     struct time *tp;
  475. {
  476.     static struct tm tm;
  477.     struct tm *tx;
  478.     long now;
  479.  
  480.     tm.tm_year = dp->da_year - 1900;
  481.     tm.tm_mon = dp->da_mon - 1;
  482.     tm.tm_mday = dp->da_day;
  483.     tm.tm_hour = tp->ti_hour;
  484.     tm.tm_min = tp->ti_min;
  485.     tm.tm_sec = tp->ti_sec;
  486.     /* This desperately needs to be fixed.  How? */
  487.     time(&now);
  488.     tx = localtime(&now);
  489.     tm.tm_isdst = tx->tm_isdst;
  490.     return mktime(&tm);
  491. }
  492.  
  493. /*****************************************************************************\
  494. *                Timers, I/O and scheduling                  *
  495. \*****************************************************************************/
  496.  
  497. void
  498. register_io(fd, event)
  499.     int fd;
  500.     void *event;
  501. {
  502.     struct io *evp;
  503.  
  504.     if (!(evp = mallocw(sizeof *evp)))
  505.     {
  506.     tprintf("register_io: no memory for event\n");
  507.     where_outta_here(1);
  508.     }
  509.     evp->fd = fd;
  510.     evp->event = event;
  511.     evp->next = Events;
  512.     Events = evp;
  513. }
  514.  
  515. void
  516. unregister_io(fd)
  517.     int fd;
  518. {
  519.     struct io *evp, *evc;
  520.  
  521.     for (evp = 0, evc = Events; evc->fd != fd; evp = evc, evc = evc->next)
  522.     ;
  523.     if (!evc)
  524.     {
  525.     tprintf("unregister_io: unknown fd\n");
  526.     return;
  527.     }
  528.     if (evp)
  529.     evp->next = evc->next;
  530.     else
  531.     Events = evc->next;
  532.     j_free(evc);
  533. }
  534.  
  535. static void
  536. ouch(int sig)
  537. {
  538.     struct sigaction sa;
  539.  
  540.     sa.sa_handler = SIG_DFL;
  541.     sa.sa_flags = 0;
  542.     sigaction(SIGSEGV, &sa, (struct sigaction *) 0);
  543. #ifdef SIGBUS
  544.     sigaction(SIGBUS, &sa, (struct sigaction *) 0);
  545. #endif
  546.     if (fork() == 0)
  547.     {
  548.     sigaction(sig, &sa, (struct sigaction *) 0);
  549.     raise(sig);
  550.     }
  551.     detach_all_asy();
  552.     exit(1);
  553. }
  554.  
  555. static void
  556. ding(int i)
  557. {
  558.     extern struct timer *Timers;
  559.     static struct timeval tv;
  560.     struct timeval *tvp;
  561.     static fd_set fds;
  562.     struct io *evp;
  563.     long oclock;
  564.  
  565.     /* do pending output */
  566.     if (!i)
  567.     {
  568.     tflush();
  569.     rflush();
  570.     }
  571.     /* collect input events to wait on */
  572.     FD_ZERO(&fds);
  573.     for (evp = Events; evp; evp = evp->next)
  574.     FD_SET(evp->fd, &fds);
  575.     /* get time until next timer; if zero, fake a very large one */
  576.     /* if we have a nonzero argument, we're a timer tick; poll, don't block */
  577.     if (i)
  578.     {
  579.     tv.tv_sec = tv.tv_usec = 0;
  580.     tvp = &tv;
  581.     }
  582.     else if (!Timers)
  583.     tvp = 0;
  584.     else
  585.     {
  586.     tv.tv_sec = (Timers->expiration - Clock) * MSPTICK;
  587.     if (tv.tv_sec <= 0)
  588.         tv.tv_sec = 0;
  589.     tv.tv_usec = (tv.tv_sec % 1000) * 1000;
  590.     tv.tv_sec /= 1000;
  591.     tvp = &tv;
  592.     }
  593.     /* check for I/O */
  594.     select(FD_SETSIZE, &fds, 0, 0, tvp);
  595.     /* signal events for pending I/O */
  596.     for (evp = Events; evp; evp = evp->next)
  597.     {
  598.     if (FD_ISSET(evp->fd, &fds))
  599.         psignal(evp->event, 1);
  600.     }
  601.     /* run any due timers */
  602.     psignal(&Tick, 1);
  603.     /* and update the system time */
  604.     oclock = Clock;
  605.     Clock = msclock() / MSPTICK;
  606.     Tick = Clock - oclock;
  607. }
  608.  
  609.  
  610. static void
  611. init_tick(void)
  612. {
  613.     struct sigaction sa;
  614.     struct itimerval it;
  615.  
  616.     sa.sa_flags = 0;
  617.     sa.sa_handler = ding;
  618.     sigaction(SIGALRM, &sa, (struct sigaction *) 0);
  619.     it.it_interval.tv_sec = 0;
  620.     it.it_interval.tv_usec = MSPTICK * 1000;
  621.     it.it_value = it.it_interval;
  622.     setitimer(ITIMER_REAL, &it, (struct itimerval *) 0);
  623. }
  624.  
  625. static void
  626. deinit_tick(void)
  627. {
  628.     struct itimerval it;
  629.  
  630.     it.it_interval.tv_sec = it.it_interval.tv_usec = 0;
  631.     it.it_value = it.it_interval;
  632.     setitimer(ITIMER_REAL, &it, (struct itimerval *) 0);
  633. }
  634.  
  635. void
  636. init_sys(int no_itimer)
  637. {
  638.     struct sigaction sa;
  639.  
  640.     init_time();
  641.     register_io(0, &Keyboard);
  642.     sa.sa_handler = ouch;
  643.     sa.sa_flags = 0;
  644.     sigaction(SIGSEGV, &sa, (struct sigaction *) 0);
  645. #ifdef SIGBUS
  646.     sigaction(SIGBUS, &sa, (struct sigaction *) 0);
  647. #endif
  648.     if (!no_itimer)
  649.     init_tick();
  650. }
  651.  
  652. void
  653. deinit_sys()
  654. {
  655.     deinit_tick();
  656.     unregister_io(0);
  657. }
  658.  
  659. void
  660. giveup()
  661. {
  662.     /* suspend heartbeat */
  663.     deinit_tick();
  664.     /* block for I/O */
  665.     ding(0);
  666.     /* and reactivate the tick */
  667.     init_tick();
  668. }
  669.  
  670. #ifdef SHELL
  671.  
  672. int
  673. doshell(int argc, char **argv, void *p)
  674. {
  675.     struct sigaction sa, old_int, old_quit;
  676.     int ac, pid;
  677.     int pi[2];
  678.     char *av[4];
  679.  
  680.     /*
  681.      * Under *ix, one would expect ! or shell to work like in other *ix
  682.      * programs.  Since we don't really want to emulate DOS doshell()'s
  683.      * special handling for argv[1] == "/c" anyway :-) we will handle
  684.      * this properly.
  685.      *
  686.      * argc < 2: ${SHELL:-/bin/sh}
  687.      * >= 2: concatenate and /bin/sh -c it (NOT $SHELL)!
  688.      */
  689.     if (!sm_usestdio())
  690.     {
  691.     tprintf("Not running on NOS console\n");
  692.     return 1;
  693.     }
  694.     if (pipe(pi) == -1)
  695.     {
  696.     tprintf("Can't create pipe for subprocess\n");
  697.     return 1;
  698.     }
  699.     switch (pid = fork())
  700.     {
  701.     case -1:
  702.     tprintf("Fork failed\n");
  703.     return 1;
  704.     case 0:
  705.     close(pi[0]);
  706.     ac = 1;
  707.     if (argc > 1 || !(av[0] = getenv("SHELL")))
  708.         av[0] = "/bin/sh";
  709.     if (argc > 1)
  710.     {
  711.         av[ac++] = "-c";
  712.         av[ac++] = argv[1];
  713.     }
  714.     av[ac] = 0;
  715.     execv(av[0], av);
  716.     _exit(1);
  717.     default:
  718.     close(pi[1]);
  719.     iosuspend();
  720.     unregister_io(0);
  721.     register_io(pi[0], &Shell);
  722.     /* signal handling... */
  723.     sigemptyset(&sa.sa_mask);
  724.     sa.sa_flags = 0;
  725.     sa.sa_handler = SIG_IGN;
  726.     sigaction(SIGINT, &sa, &old_int);
  727.     sigaction(SIGQUIT, &sa, &old_quit);
  728.     pwait(&Shell);
  729.     sigaction(SIGQUIT, &old_quit, 0);
  730.     sigaction(SIGINT, &old_int, 0);
  731.     unregister_io(pi[0]);
  732.     close(pi[0]);
  733.     register_io(0, &Keyboard);
  734.     ioresume();
  735.     }
  736.     return 0;
  737. }
  738.  
  739. #endif
  740.